﻿#pragma once
#include "AsQBasicGlobal.h"
#include <QVector>

/*
  notice:
	only basic d types can be used.
*/
__AS_JY(Update 2022)
template<typename Type>
class AsOptions {
public:
	AsOptions(bool isLooping = true);
	AsOptions(const QVector<Type>& optionList, bool isLooping = true);
private:
	QVector<Type>	m_optionList;
	int				m_current;
	bool			m_isLooping;
public:
	void addOption(Type opt);
	bool delOption(Type opt);
	void clrOption();
	Type current();
	void selectBegin();
	void selectEnd();
	void selectNext();
	void selectLast();
	bool selectOption(Type opt);
	bool selectIndex(int i);
	void selectNearest(Type opt);
	void setLooping(bool isLooping);
};

template<typename Type>
AsOptions<Type>::AsOptions(bool isLooping) {
	m_current = 0;
	m_isLooping = isLooping;
}

template<typename Type>
AsOptions<Type>::AsOptions(const QVector<Type>& optionList, bool isLooping) {
	m_optionList = optionList;
	m_current = 0;
	m_isLooping = isLooping;
}

template<typename Type>
void AsOptions<Type>::addOption(Type opt) {
	m_optionList.push_back(opt);
}

template<typename Type>
bool AsOptions<Type>::delOption(Type opt) {
	for (QVector<Type>::iterator i = m_optionList.begin(); i != m_optionList.end(); i++) {
		if (*i == opt) {
			m_optionList.erase(i);
			if (m_current >= m_optionList.size()) m_current = m_optionList.size() - 1;
			return true;
		}
	}
	return false;
}

template<typename Type>
void AsOptions<Type>::clrOption() {
	m_optionList.clear();
	m_current = 0;
}

template<typename Type>
Type AsOptions<Type>::current() {
	if (m_current < 0 || m_current >= m_optionList.size()) {
		throw AsException(AsException::CodeOptions_IndexOutOfRange, "current out of range");
	}
	else {
		return m_optionList[m_current];
	}
}

template<typename Type>
void AsOptions<Type>::selectBegin() {
	m_current = 0;
}

template<typename Type>
void AsOptions<Type>::selectEnd() {
	m_current = m_optionList.size() - 1;
}

template<typename Type>
void AsOptions<Type>::selectNext() {
	if (m_current < m_optionList.size() - 1) {
		m_current++;
	}
	else if (m_isLooping) {
		m_current = 0;
	}
}

template<typename Type>
void AsOptions<Type>::selectLast() {
	if (m_current > 0) {
		m_current--;
	}
	else if (m_isLooping) {
		m_current = m_optionList.size() - 1;
	}
}

template<typename Type>
bool AsOptions<Type>::selectOption(Type opt) {
	int index = 0;
	for (QVector<Type>::iterator i = m_optionList.begin(); i != m_optionList.end(); i++) {
		if (*i == opt) {
			m_current = index;
			return true;
		}
		index++;
	}
	return false;
}

template<typename Type>
bool AsOptions<Type>::selectIndex(int i) {
	if (i < 0 || i >= m_optionList.size()) return false;
	m_current = i;
	return true;
}

template<typename Type>
void AsOptions<Type>::selectNearest(Type opt) {
	if (m_optionList.isEmpty()) return;
	Type min = (opt - m_optionList.front() >= 0) ? (opt - m_optionList.front()) : (m_optionList.front() - opt);
	int minpos = 0;
	for (int i = 0; i < m_optionList.size(); i++) {
		Type tmp = (opt - m_optionList[i] >= 0) ? (opt - m_optionList[i]) : (m_optionList[i] - opt);
		if (min > tmp) {
			min = tmp;
			minpos = i;
		}
	}
	m_current = minpos;
}

template<typename Type>
void AsOptions<Type>::setLooping(bool isLooping) {
	m_isLooping = isLooping;
}

